﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GameEngine.Entities;
using Microsoft.Xna.Framework;
using GameEngine.Managers.IManagers;
using System.Diagnostics;

namespace GameEngine.EntityComponents
{
    public class MoveableComponent : IEntityComponent
    {
        public enum State { InAir, OnGround, Climbing, Dead }
        public enum MoveDir { Forward, Backward }

        private AbstractEntity entity;
        private IInputManager inputManager;
        private IPhysicsManager physicsManager;
        private ISceneManager sceneManager;
        public float mass = 2.0f;
        public float xVelocity = 0f;
        public float yVelocity = 0f;
        public float latestXMove = 0f;
        public float latestYMove = 0f;
        private static float updatesPerSecond = 30.0f;
        private DateTime lastUpdate = DateTime.Now;
        private float moveSpeed = 2.0f;
        public State movementState = State.OnGround;
        public MoveDir movementDirection = MoveDir.Forward;
        public Boolean isNPC = false;

        private bool specialAction1 = false;

        public MoveableComponent(AbstractEntity entity, float mass, Boolean isNPC)
        {
            inputManager = (IInputManager)entity.game.Services.GetService(typeof(IInputManager));
            physicsManager = (IPhysicsManager)entity.game.Services.GetService(typeof(IPhysicsManager));
            sceneManager = (ISceneManager)entity.game.Services.GetService(typeof(ISceneManager));
            movementDirection = MoveableComponent.MoveDir.Forward;
            this.entity = entity;
            this.mass = mass;
            this.isNPC = isNPC;
        }

        public void Update(GameTime gameTime)
        {
            TimeSpan timePassed = DateTime.Now - lastUpdate;

            if ((timePassed.TotalMilliseconds) > (1000 / updatesPerSecond))
            {
                if (movementState == State.InAir)
                    yVelocity += ((physicsManager.calcGravityPull(mass) / ((float)timePassed.TotalMilliseconds)) * 100);

                if (isNPC)
                {
                    if(movementDirection == MoveableComponent.MoveDir.Backward)
                        xVelocity = -moveSpeed;
                    if (movementDirection == MoveableComponent.MoveDir.Forward)
                        xVelocity = moveSpeed;
                }
                else
                {
                    if (inputManager.IsBackwardPressed())
                    {
                        xVelocity = -moveSpeed;
                        movementDirection = MoveDir.Backward;
                    }
                    else if (inputManager.IsForwardPressed())
                    {
                        xVelocity = moveSpeed;
                        movementDirection = MoveDir.Forward;
                    }
                    else
                        xVelocity = 0;

                    if (inputManager.IsAPressed() && movementState == State.OnGround)
                        yVelocity = -((3f / ((float)timePassed.TotalMilliseconds)) * 100);

                    if (inputManager.IsSpecialAction1Pressed())
                        specialAction1 = true;
                    else
                        specialAction1 = false;
                }

                lastUpdate = DateTime.Now;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether this instance is a NPC.
        /// </summary>
        /// <value>
        ///   <c>true</c> if this instance is NPC; otherwise, <c>false</c>.
        /// </value>
        public bool IsNPC
        {
            get { return isNPC; }
            set { isNPC = value; }
        }

        /// <summary>
        /// Gets or sets a value indicating whether [special action1].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [special action1]; otherwise, <c>false</c>.
        /// </value>
        public bool SpecialAction1
        {
            get { return specialAction1; }
            set { specialAction1 = value; }
        }

        public void CollideWith(AbstractEntity target, bool isX, bool isY)
        {}

        /// <summary>
        /// Collides the with environment.
        /// </summary>
        /// <param name="moveDir">The move dir.</param>
        public void CollideWithEnvironment(MoveDir moveDir)
        {
            if (isNPC)
            {
                if(moveDir == MoveableComponent.MoveDir.Backward)
                    movementDirection = MoveableComponent.MoveDir.Forward;
                if(moveDir == MoveableComponent.MoveDir.Forward)
                    movementDirection = MoveableComponent.MoveDir.Backward;
            }
        }
    }
}
